package com.youlu.campus.admin.auth.service.impl;

import com.alibaba.fastjson.JSON;
import com.youlu.campus.admin.auth.entity.SystemUser;
import com.youlu.campus.admin.auth.service.PasswordService;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.crypto.RandomNumberGenerator;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class PasswordServiceImpl implements PasswordService {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    protected RandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator();

    @Value("${password.algorithmName:md5}")
    private String algorithmName = "md5";

    @Value("${password.hashIterations:2}")
    private int hashIterations = 2;

    protected static String HASH_PASSWORD_SALT_FORMATTER = "%s\t%s\t%s";

    public String generatorSalt() {
        return randomNumberGenerator.nextBytes().toHex();
    }

    @Override
    public void encryptPassword(SystemUser user) {
        logger.debug("encryptPassword user begin:{}", JSON.toJSONString(user));
        String salt = generatorSalt();
        logger.debug("gen salt:{}", salt);
        user.setSalt(salt);

        String newPassword = new SimpleHash(algorithmName, user.getEncPwd(),
                getCredentialsSalt(user), hashIterations).toHex();
        user.setEncPwd(newPassword);
        logger.debug("encryptPassword user end :{}", JSON.toJSONString(user));
    }

    @Override
    public boolean validPassword(SystemUser user, String oldPwd) {
        logger.debug("encryptPassword user begin:{}", JSON.toJSONString(user));
        String oldEncPwd = new SimpleHash(algorithmName, oldPwd, getCredentialsSalt(user),
                hashIterations).toHex();
        logger.debug("validPassword db password:{}, oldEncPwd:{} ", user.getEncPwd(), oldEncPwd);
        boolean result = StringUtils.equalsIgnoreCase(user.getEncPwd(), oldEncPwd);
        logger.debug("encryptPassword user end :{}", JSON.toJSONString(user));
        return result;
    }

    @Override
    public ByteSource getPasswordCredentialsSalt(SystemUser user) {
        logger.debug("getCredentialsSalt user:{}", user);
        ByteSource byteSource = ByteSource.Util.bytes(String.format(HASH_PASSWORD_SALT_FORMATTER,
                user.getLoginName(), user.getDomain(), user.getSalt()));
        logger.debug("getCredentialsSalt byteSource:{}", JSON.toJSONString(byteSource));
        return byteSource;
    }

    @Override
    public ByteSource getCredentialsSalt(SystemUser user) {
        logger.debug("getCredentialsSalt user:{}", JSON.toJSONString(user));
        ByteSource byteSource = ByteSource.Util.bytes(String.format(HASH_PASSWORD_SALT_FORMATTER,
                user.getLoginName(), user.getDomain(), user.getSalt()));
        logger.debug("getCredentialsSalt byteSource:{}", JSON.toJSONString(byteSource));
        return byteSource;
    }
}
